using System;
using System.ComponentModel;
using System.Net;
using System.Security;
using System.Text;
using System.Xml.Linq;

namespace HeadCounter.Armourer.Requesters
{
    public enum ReqeusterDataType
    {
        Item, Character
    }

    public abstract class WebRequester
    {
        private const int MaxAttempts = 5;

        private WebClient CreateWebClient()
        {
            // todo add proper support for proxies and the like as in RAWR i guess

            var client = new WebClient()
                             {
                                 Encoding = Encoding.UTF8,
                                 Proxy = WebRequest.DefaultWebProxy
                             };

            client.Headers.Add("user-agent", "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4");
            return client;
        }

        private bool IsFatalError(Exception ex)
        {
            // This is straight from the RAWR version but not doing anything about proxies or error
            // reporting yet.
            if (ex.Message.Contains("407") /*proxy auth required */
                || ex.Message.Contains("403") /*proxy info probably wrong, if we keep issuing requests, they will probably get locked out*/
                || ex.Message.Contains("timed out") /*either proxy required and firewall dropped the request, or armory is down*/
                || ex.Message.Contains("The remote name could not be resolved") /* DNS problems*/
                )
            {
                return true;
            }

            return false;
        }

        public abstract ReqeusterDataType GetDataType();
        public abstract bool HasWork();
        public abstract XElement RequestData(BackgroundWorker worker);

        protected string GetWebData(Uri uri)
        {
            string data = "";
            var armouryClient = CreateWebClient();

            var downloading = true;
            while (downloading)
            {
                for (int n = 0; downloading && n < MaxAttempts; n++)
                {
                    try
                    {
                        data = armouryClient.DownloadString(uri);

                        if (!String.IsNullOrEmpty(data))
                        {
                            downloading = false;
                        }
                    }
                    catch (Exception ex)
                    {
                        if (IsFatalError(ex))
                        {
                            downloading = false;
                            break;
                        }
                    }
                }
            }

            return data;
        }

        // todo handle these exceptions properly

        protected void GetWebFile(string address, string fileName)
        {
            try
            {
                CreateWebClient().DownloadFile(address, fileName);
            }
            catch (WebException)
            {
                // address wrong or cannot download
            }
            catch (SecurityException)
            {
                // cannot write to local file location
            }
            catch (Exception ex)
            {
                if (IsFatalError(ex)) return;
                throw;
            }
        }
    }
}